#include "GS_Play.h"
#include "GameCore\Device_Base.h"
#include "GameCore\Screen.h"
#include "GameCore\PhysicsManager.h"
#include "GameCore\FontManager.h"
#include "GameCore\StringManager.h"

void GS_Play::Init()
{
	camera = new Camera();

	camera->SetCameraLookAt(0.0f, 0.0f, 50.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f);
	Device_Base::GetInstance()->SetCameraActivated(camera);

	Device_Base::GetInstance()->SetProjectionOrthoCenterMatrix(Device_Base::GetInstance()->GetWidth()
		, Device_Base::GetInstance()->GetHeight(), 0.01f, 100.0f);

	simpleProgram = ShaderManager::GetInstance()->GetProgramFromFile("2D_vs.txt", "2D_fs.txt");

	//fireworkProgram = ShaderManager::GetInstance()->GetProgramFromFile("sdcard/firework_vs.txt", "sdcard/firework_fs.txt");

	Kaleidoscopes = TextureManager::GetInstance()->LoadTexture("gem.tga");

	spriteDog = SpriteManager::GetInstance()->LoadSpriteFromXMLFile("dog.sprite");

	dog = new GameObject2D();
	dog->SetSprite(spriteDog);
	dog->SetAnim(spriteDog->GetAnim(0));
	dog->EnableAnim(true);

	Device_Base::GetInstance()->SetClearColorBuffer(0.0f, 0.0f, 0.0f, 1.0f);
	renderTarget = new RenderTarget("color1", min(Screen::GetInstance()->GetWidth(), Screen::GetInstance()->GetHeight()), min(Screen::GetInstance()->GetWidth(), Screen::GetInstance()->GetHeight()), true);
	renderTarget->Init();
	float uv[6] = { 0.0f, 1.0f, 0.0f, 0.0f, 0.866f, 0.5f };
	float base = 0.75f;
	float altitude = sqrt(base*base - pow(base*0.5f, 2));
	int column = ceil(((Screen::GetInstance()->GetRatio() / altitude) + 1)*2);
	int row = ceil((1.0f / base + 1)*2);
	float* data = new float[5*column*row*6];
	float* dataPos = data;
	vertexCount = 0;
	for (int i = 0; i < column; i++)
	{
		for (int j = row - 1; j >= 0; j--)
		{
			float x = i*altitude - Screen::GetInstance()->GetRatio();
			float y = j*base - 1.0f - (i % 2) * base* 0.5f;
			float z = -1.0f;
			int uvIndex1 = (row - 1 - j) % 3 - i % 2;
			if (uvIndex1 < 0)
			{
				uvIndex1 += 3;
			}
			else if (uvIndex1 > 2)
			{
				uvIndex1 -= 3;
			}
			int uvIndex2 = uvIndex1 + 1;
			if (uvIndex2 < 0)
			{
				uvIndex2 += 3;
			}
			else if (uvIndex2 > 2)
			{
				uvIndex2 -= 3;
			}
			int uvIndex3 = uvIndex2 + 1;
			if (uvIndex3 < 0)
			{
				uvIndex3 += 3;
			}
			else if (uvIndex3 > 2)
			{
				uvIndex3 -= 3;
			}
			dataPos[0] = x;
			dataPos[1] = y;
			dataPos[2] = z;
			dataPos[3] = uv[uvIndex1*2];
			dataPos[4] = uv[uvIndex1*2 + 1];
			dataPos += 5;
			//---------------------------
			dataPos[0] = x;
			dataPos[1] = y - base;
			dataPos[2] = z;
			dataPos[3] = uv[uvIndex2*2];
			dataPos[4] = uv[uvIndex2*2 + 1];
			dataPos += 5;
			//---------------------------
			dataPos[0] = x + altitude;
			dataPos[1] = y - base*0.5f;
			dataPos[2] = z;
			dataPos[3] = uv[uvIndex3 * 2];
			dataPos[4] = uv[uvIndex3 * 2 + 1];
			dataPos += 5;
			//---------------------------
			dataPos[0] = x + altitude;
			dataPos[1] = y - base*0.5f;
			dataPos[2] = z;
			dataPos[3] = uv[uvIndex3 * 2];
			dataPos[4] = uv[uvIndex3 * 2 + 1];
			dataPos += 5;
			//---------------------------
			dataPos[0] = x;
			dataPos[1] = y - base;
			dataPos[2] = z;
			dataPos[3] = uv[uvIndex2 * 2];
			dataPos[4] = uv[uvIndex2 * 2 + 1];
			dataPos += 5;
			//---------------------------
			dataPos[0] = x + altitude;
			dataPos[1] = y - base*1.5f;
			dataPos[2] = z;
			dataPos[3] = uv[uvIndex1 * 2];
			dataPos[4] = uv[uvIndex1 * 2 + 1];
			dataPos += 5;
			//---------------------------
			vertexCount += 6;
		}
	}
	vboKaleidoscopes = new VBO(VBO::VBO_TARGET_ARRAY_BUFFER);
	vboKaleidoscopes->usage = VBO::VBO_USAGE_STATIC_DRAW;
	vboKaleidoscopes->SetAttributeOffset(ATTRIBUTE_FLOAT3_POSITION, 0);
	vboKaleidoscopes->SetAttributeOffset(ATTRIBUTE_FLOAT2_TEXCOORD_DIFFUSE, 3 * sizeof(float));
	Device_Base::GetInstance()->CreateVBO(vboKaleidoscopes, (char*)data, vertexCount * 5 * sizeof(float));
	SafeDeleteArray(data);
	InitPhysics();
	InitObject3Ds();
	FontManager::GetInstance()->LoadFontFromFile("arial.fnt");
}
void GS_Play::Release()
{
	CleanupPhysics();
	SafeDelete(camera);
	SafeDelete(vboKaleidoscopes);
}
void GS_Play::Update(float timeTotal, float timeDelta)
{
	dog->Update(timeDelta);
	PhysicsManager::GetInstance()->Update(timeDelta);
	btTransform trans;
	sphereDog->getMotionState()->getWorldTransform(trans);
	printf("world pos = %f,%f,%f\n", float(trans.getOrigin().getX()), float(trans.getOrigin().getY()), float(trans.getOrigin().getZ()));
	dog->SetPosition(float(trans.getOrigin().getX()), float(trans.getOrigin().getY()));
	static float timeCount = 0.0f;
	timeCount += timeDelta;
	if (timeCount > 5.0f)
	{
		timeCount = 0.0f;
		if (boxTest)
		{
			boxTest->setActivationState(ACTIVE_TAG);
			btVector3 impulse = btVector3(rand(), rand(), rand());
			impulse.normalize();
			float impulseStrength = 0.7f;
			impulse *= impulseStrength;
			btVector3 relPos = btVector3(float(trans.getOrigin().getX()) + 0.05f, float(trans.getOrigin().getY()), float(trans.getOrigin().getZ()));
			sphereDog->applyImpulse(impulse, relPos);
		}
	}
}
void GS_Play::Render()
{
	Device_Base::GetInstance()->SetClearColorBuffer(0.0f, 0.0f, 0.0f, 1.0f);
	Device_Base::GetInstance()->ClearColorDepthStencilBuffer(true, false, false);
	Device_Base::GetInstance()->PushRenderTarget(renderTarget);
	Device_Base::GetInstance()->ClearColorDepthStencilBuffer(true, true, false);
	Device_Base::GetInstance()->SetViewport(0, 0, min(Screen::GetInstance()->GetWidth(), Screen::GetInstance()->GetHeight()), min(Screen::GetInstance()->GetWidth(), Screen::GetInstance()->GetHeight()));
	Matrix m = Device_Base::GetInstance()->GetMatrixProjection();
	Device_Base::GetInstance()->SetProjectionOrthoCenterMatrix(2.0f, 2.0f, 0.01f, 200.0f);
	Device_Base::GetInstance()->UseProgram(simpleProgram);
	//Device_Base::GetInstance()->SetCameraActivated(camera);
	//Device_Base::GetInstance()->BeginDraw2DLogical();
	//Device_Base::GetInstance()->Draw2DTextureFullViewport(Kaleidoscopes);
	BlendState blendState;
	Device_Base::GetInstance()->SetBlendState(blendState);
	Device_Base::GetInstance()->EnableBlend();
	//------------------------------------------
	Device_Base::GetInstance()->UseProgram(simpleProgram);
	Device_Base::GetInstance()->DisableDepthTest();
	Device_Base::GetInstance()->SetUniformTexture(UNIFORM_TEXTURE_DIFFUSE, TextureManager::GetInstance()->GetTexture("Symbol.tga"));
	for (int i = 0; i < object3Ds.size(); i++)
	{
		object3Ds[i]->Render();
	}
	//------------------------------------------
	//Device_Base::GetInstance()->EndDraw2D();
	Device_Base::GetInstance()->PopRenderTarget();
	Device_Base::GetInstance()->SetProjectionMatrix(m);
	Device_Base::GetInstance()->SetViewport(0, 0, Screen::GetInstance()->GetWidth(), Screen::GetInstance()->GetHeight());
	//Device_Base::GetInstance()->SetProjectionOrthoCenterMatrix(Device_Base::GetInstance()->GetWidth()
	//	, Device_Base::GetInstance()->GetHeight(), 0.01f, 100.0f);
	
	Device_Base::GetInstance()->BeginDraw2DLogical();
	//Device_Base::GetInstance()->Draw2DTextureFullViewport(renderTarget->GetColorTexture());
	Device_Base::GetInstance()->BindVBO(vboKaleidoscopes);
	Device_Base::GetInstance()->UpdateVertexAttribPointer();
	//Device_Base::GetInstance()->SetUniformTexture(UNIFORM_TEXTURE_DIFFUSE, Kaleidoscopes);
	Device_Base::GetInstance()->SetUniformTexture(UNIFORM_TEXTURE_DIFFUSE, renderTarget->GetColorTexture());
	Device_Base::GetInstance()->SetUniformMatrix(UNIFORM_MATRIX_MODEL, Device_Base::GetInstance()->GetMatrixWorld());
	Device_Base::GetInstance()->SetUniformMatrix(UNIFORM_MATRIX_PROJECTION, Device_Base::GetInstance()->GetMatrixProjection());
	//Device_Base::GetInstance()->DisableBlend();
	Device_Base::GetInstance()->DrawArray(Device_Base::PRIMITIVE_TRIANGLE_LIST, 0, vertexCount);
	dog->Render();
	PhysicsManager::GetInstance()->RenderDebug();
	Program* textPrg = ShaderManager::GetInstance()->GetProgramFromFile("Text_vs.txt", "Text_fs.txt");
	if (textPrg)
	{
		Device_Base::GetInstance()->UseProgram(textPrg);
		Device_Base::GetInstance()->SetUniformVec4f(UNIFORM_FLOAT4_COLOR_AMBIENT, Vector4f(0.0f,0.0f,1.0f,1.0f));
	}
	Font* font = FontManager::GetInstance()->GetFontByFileName("arial.fnt");
	if (font)
	{
		FontManager::GetInstance()->DrawASCII(0, 0, font, "W\nork harder!!!");
		StringRecord* record = StringManager::GetInstance()->GetStringRecord("STR_OK");
		if (record)
		{
			int length = 0;
			unsigned long* buffer = NULL;
			FontManager::GetInstance()->WrapTextUTF8(record->VN, 1.5f, font, &buffer, &length);
			//FontManager::GetInstance()->DrawUTF8(0, 0.5f, font, record->VN);
			FontManager::GetInstance()->DrawUTF8(-1.5f, 0.9f, font, buffer, length);
		}
	}
	Device_Base::GetInstance()->EndDraw2D();

	//-------------------------------------------------
}
void GS_Play::InitPhysics()
{

	PhysicsManager::GetInstance()->Init();
	//PhysicsManager::GetInstance()->AddBoxShape(Vector3f(0, -51.0f, 0), Vector3f(50.0f, 50.0f, 50.0f), 0.0f);
	PhysicsManager::GetInstance()->AddBoxShape(Vector3f(0, -1.1f, 0), Vector3f(Screen::GetInstance()->GetRatio(), 0.1f, 1.0f), 0.0f);
	PhysicsManager::GetInstance()->AddBoxShape(Vector3f(0, 1.1f, 0), Vector3f(Screen::GetInstance()->GetRatio(), 0.1f, 1.0f), 0.0f);
	//PhysicsManager::GetInstance()->AddBoxShape(Vector3f(Screen::GetInstance()->GetRatio(), 0.0f, 0), Vector3f(0.1f, 1.0f, 1.0f), 0.0f);
	//PhysicsManager::GetInstance()->AddBoxShape(Vector3f(-Screen::GetInstance()->GetRatio(), 0.0f, 0), Vector3f(0.1f, 1.0f, 1.0f), 0.0f);
	PhysicsManager::GetInstance()->AddBoxShape(Vector3f(1.1f, 0.0f, 0), Vector3f(0.1f, 1.0f, 1.0f), 0.0f);
	PhysicsManager::GetInstance()->AddBoxShape(Vector3f(-1.1f, 0.0f, 0), Vector3f(0.1f, 1.0f, 1.0f), 0.0f);
	PhysicsManager::GetInstance()->AddBoxShape(Vector3f(0.0f, 0.0f, 1.0f), Vector3f(Screen::GetInstance()->GetRatio(), 1.0f, 0.1f), 0.0f);
	PhysicsManager::GetInstance()->AddBoxShape(Vector3f(0.0f, 0.0f, -1.0f), Vector3f(Screen::GetInstance()->GetRatio(), 1.0f, 0.1f), 0.0f);

	sphereDog = PhysicsManager::GetInstance()->AddSphereShape(Vector3f(-0.1f, 0.2f, 0), 0.15f, 1.0f);
	boxTest = PhysicsManager::GetInstance()->AddBoxShape(Vector3f(0, 0.5f, 0), Vector3f(0.1f, 0.1f, 0.1f), 1.0f);
}
void GS_Play::CleanupPhysics()
{
	PhysicsManager::GetInstance()->Release();
}
void GS_Play::OnTouchDown(unsigned int id, float x, float y)
{
	if (PhysicsManager::GetInstance()->GetDynamicWorld())
	{
		Vector2f logicalPos = Screen::GetInstance()->ScreenToLogical(x, y);
	
		btCollisionWorld::AllHitsRayResultCallback rayCallback(btVector3(logicalPos.x, logicalPos.y, 50.0f)
			, btVector3(logicalPos.x, logicalPos.y, -50.0f));
		PhysicsManager::GetInstance()->GetDynamicWorld()->rayTest(btVector3(logicalPos.x, logicalPos.y, 50.0f)
			, btVector3(logicalPos.x, logicalPos.y, -50.0f), rayCallback);
		if (rayCallback.hasHit())
		{
			for (int i = 0; i < rayCallback.m_collisionObjects.size(); i++)
			{
				btRigidBody* body = (btRigidBody*)btRigidBody::upcast(rayCallback.m_collisionObjects[i]);
				if (body && body->getCollisionFlags() != btCollisionObject::CF_STATIC_OBJECT)
				{
					body->setActivationState(ACTIVE_TAG);
					btVector3 impulse = btVector3(rand(), rand(), rand());
					impulse.normalize();
					float impulseStrength = 0.7f;
					impulse *= impulseStrength;
					btVector3 relPos = rayCallback.m_hitPointWorld[i];
					body->applyImpulse(impulse, relPos);
				}
			}
		}
		
	}
}
void GS_Play::OnTouchUp(unsigned int id, float x, float y)
{
}
void GS_Play::OnTouchMove(unsigned int id, float x, float y)
{
}
void GS_Play::InitObject3Ds()
{
	Sprite* symbol = SpriteManager::GetInstance()->LoadSpriteFromXMLFile("Symbol.sprite");
	float scale = 0.005f;
	for (int i = 0; i < symbol->GetModuleCount(); i++)
	{
		SpriteModule* module = symbol->GetModule(i);
		float* data = new float[6*5];
		int index = 0;
		float widthDiv2 = float(module->width) * scale;
		float heightDiv2 = float(module->width) * scale;
		float z = 0.0f;
		data[index++] = -widthDiv2;
		data[index++] = heightDiv2;
		data[index++] = z;
		data[index++] = module->texcoord.left;
		data[index++] = module->texcoord.top;

		data[index++] = -widthDiv2;
		data[index++] = -heightDiv2;
		data[index++] = z;
		data[index++] = module->texcoord.left;
		data[index++] = module->texcoord.bottom;

		data[index++] = widthDiv2;
		data[index++] = -heightDiv2;
		data[index++] = z;
		data[index++] = module->texcoord.right;
		data[index++] = module->texcoord.bottom;

		data[index++] = -widthDiv2;
		data[index++] = heightDiv2;
		data[index++] = z;
		data[index++] = module->texcoord.left;
		data[index++] = module->texcoord.top;

		data[index++] = widthDiv2;
		data[index++] = -heightDiv2;
		data[index++] = z;
		data[index++] = module->texcoord.right;
		data[index++] = module->texcoord.bottom;

		data[index++] = widthDiv2;
		data[index++] = heightDiv2;
		data[index++] = z;
		data[index++] = module->texcoord.right;
		data[index++] = module->texcoord.top;

		VBO* vbo = new VBO(VBO::VBO_TARGET_ARRAY_BUFFER);
		//vbo->vertexCount = 6;
		vbo->usage = VBO::VBO_USAGE_STATIC_DRAW;
		vbo->SetAttributeOffset(ATTRIBUTE_FLOAT3_POSITION, 0);
		vbo->SetAttributeOffset(ATTRIBUTE_FLOAT2_TEXCOORD_DIFFUSE, 3 * sizeof(float));
		Device_Base::GetInstance()->CreateVBO(vbo, (char*)data, 6 * 5 * sizeof(float));
		SafeDeleteArray(data);

		btRigidBody* body = PhysicsManager::GetInstance()->AddBoxShape(Vector3f(0, 0, 0), Vector3f(widthDiv2, heightDiv2, 0.01f), 0.5f);

		GameObject3DPhysics* object = new GameObject3DPhysics(vbo, body);

		object3Ds.push_back(object);
	}
}